home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / adafront.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  15KB  |  529 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9.  
  10. #include "hdr.h"
  11. #include "ada.h"
  12. #include "ifile.h"
  13. #include "miscp.h"
  14. #include "libfp.h"
  15. #include "actionp.h"
  16. #include "adaredp.h"
  17. #include "prsutilp.h"
  18. #include "prserrp.h"
  19. #include "adalexp.h"
  20. #include "adaprsp.h"
  21.  
  22. #include "vars.h"
  23. #include "libhdr.h"
  24. #include "libp.h"
  25. #include "librp.h"
  26. #include "libwp.h"
  27. #include "setp.h"
  28. #include "dbxp.h"
  29. #include "arithp.h"
  30. #include "smiscp.h"
  31. #include "chapp.h"
  32. #include "dclmapp.h"
  33. #include "sspansp.h"
  34.  
  35.  
  36. static void lrparse();
  37. static void errorinit(struct two_pool **, struct two_pool **, int *);
  38. static void exitf(int);
  39.  
  40. /* Global variables */
  41.  
  42. struct prsstack *prs_stack = NULL,    /* Stack containing symbols */
  43. *curtok,        /* Current input token */
  44. *PREVTOK = NULL;    /* Previous input token */
  45. struct two_pool *sta_stack;        /* The state stack */
  46. /* not used by parser */
  47. FILE  *adafile,                /* File pointer for ada source file */
  48. *msgfile,                /* File pointer for msgs file */
  49. *errfile;                /* File pointer for error & debug info*/
  50.  
  51. Node any_node;    /* Special nodes to indicate
  52.                        optional elements in the ada
  53.                        syntax, or a node to be filled in */
  54. int redopt = 0;                /* Flag for printing rules */
  55. int erropt = 0;                /* Flag for printing debugging info */
  56. int termopt = 0;            /* Flag for terminal display */
  57. int debugopt = 0;            /* True if any debugging options on */
  58. int trcopt = 0;                /* True if erropt or redopt set */
  59. extern int optind;            /* global option index */
  60.  
  61. int n_sta_stack;            /* The size of the state stack */
  62. int n_prs;
  63. struct prsstack **tokens = NULL;    /* Token stack */
  64. int tokind = -1;
  65. int toksiz = 1;        /* Size of array used for token stack */
  66. int tokbottom = 0;
  67.  
  68. extern int optind;
  69. extern char *optarg;
  70.  
  71. IFILE *LIBFILE;
  72. IFILE *STUBFILE;
  73. IFILE *AISFILE;
  74. IFILE *TREFILE;
  75.  
  76. /*
  77. #include "avl.c"
  78. */
  79.  
  80. int main(int argc, char **argv)                /*;main*/
  81. {
  82.     /* Variables for reading command line and figuring out names
  83.        of files, etc. */
  84.     char *adafilename = NULL;
  85.     char *sourcefilename;
  86.     char *errfilename = NULL;
  87.     char *lib_name;
  88.     char *t_name;
  89.     int  c, n, i;
  90.     int  lib_option = FALSE;
  91.     int  new_library = FALSE;
  92.     int unbufflag = 0;
  93.     int  prefix_len, base_len, suffix_len;
  94.     char *basep;
  95.  
  96.  
  97.     Node nod;
  98.     int        compiling_predef = 0;
  99.  
  100.     /* The parser bombs on VAX if no arguments, so for now fail and
  101.      * also modify usage message to indicate that filename required
  102.      */
  103.  
  104.     /*  ***** Many options were stripped out during merge of adaprs */
  105.     /*  ***** and adasem.  Relevant ones could be returned.            */
  106.     /*  ***** Mostly debugging stuff.                                */
  107.  
  108. /*
  109.     _outtext("Parsing");
  110.     AVL_GET_DESC();
  111.     _settextwindow(15,5,15,63);
  112. */
  113.     /* Figure out what the command line means */
  114.     while ((c = getopt(argc, argv, "l:np:s:")) != EOF)
  115.     {
  116.         switch (c) {
  117.         case 'l': /* using existing library */
  118.             lib_option = TRUE;
  119.             lib_name = emalloc(strlen(optarg) + 1);
  120.             strcpy(lib_name, optarg);
  121.             break;
  122.         case 'n': /* indicates new library */
  123.             new_library = TRUE;
  124.             lib_option = TRUE;
  125.             break;
  126.         case 'p': /* parser sub options */
  127.             n = strlen(optarg);
  128.             for (i = 0; i < n; i++) {
  129.                 switch (optarg[i]) {
  130.                 case 'b' :  /* unbuffer output */
  131.                     unbufflag = 1;
  132.                     break;
  133.                 case 'e' :
  134.                     erropt = 1 ;
  135.                     break ;
  136.                 case 'r' : /* display of reductions + source */
  137.                     redopt = 1;
  138.                     break;
  139.                     /* terminal display of source + error messages */
  140.                 case 't':
  141.                     termopt = 1;
  142.                     break;
  143.                 }
  144.             }
  145.             break;
  146.         case 's':
  147.             n = strlen(optarg);
  148.             for (i=0; i <= n; i++) {
  149.                 switch(optarg[i]) {
  150.                 case 'p': /* compiling predef units */
  151.                     compiling_predef++;
  152.                     break;
  153.                 }
  154.             }
  155.             break;
  156.         default:
  157.             exitp(RC_ABORT);
  158.         }
  159.     }
  160.     if (optind < argc) {
  161.         adafilename = argv[optind];
  162.         basep = parsefile(adafilename, &prefix_len, &base_len, &suffix_len);
  163.         FILENAME = emalloc(base_len + 1);
  164.         strncpy(FILENAME, basep, base_len);
  165.         if (suffix_len == 0) { /* if suffix .ada implied */
  166.             sourcefilename = emalloc(strlen(adafilename) + 4 + 1);
  167.             strcpy(sourcefilename, adafilename);
  168.             strcat(sourcefilename, ".ada");
  169.         }
  170.         else {
  171.             sourcefilename = adafilename;
  172.         }
  173.         adafile = efopen(sourcefilename, "r", "t");
  174.     }
  175.     else {
  176.         fprintf(stderr, "Bad usage: no adafile specified.\n");
  177.         exitp(RC_ABORT);
  178.     }
  179.     t_name = libset(lib_name);
  180.     trcopt = redopt || erropt ;
  181.     debugopt = termopt || redopt || erropt ;
  182.     msgfile = efopenl(FILENAME, "msg", "w", "t");
  183.     if (trcopt) {
  184. #ifndef IBM_PC
  185.         errfile = efopenl(FILENAME, "err", "w", "t");
  186. #else
  187.         /* write to stdout on PC */
  188.         errfile = stdout;
  189. #endif
  190.     }
  191.     else {
  192.         errfilename = NULLFILENAME ;
  193.         errfile = (FILE *)0;
  194.     }
  195.  
  196.     if (unbufflag)
  197.     {
  198.         if (trcopt)
  199.             setbuf(errfile, (char *)0);
  200.         setbuf(msgfile, (char *)0);
  201.     }
  202.  
  203.  
  204. /* SEM STUFF */
  205.     STUBFILE= (IFILE *)0;
  206.     AISFILE = (IFILE *)0;
  207.     tup_init(); /* initialize tuple package */
  208.  
  209.     PREDEFNAME = predef_env();
  210.     dstrings_init(2048, 512); /* initialize dstrings package */
  211.  
  212.     rat_init(); /* initialize arithmetic and rational package*/
  213.     init_sem();
  214.     seq_node_n = 0;
  215.     any_node = node_new(as_opt);
  216.  
  217.     aisunits_read = tup_new(0);
  218.     init_symbols = tup_exp(init_symbols, (unsigned)  seq_symbol_n);
  219.     for (i=1; i<= seq_symbol_n; i++)
  220.         init_symbols[i] = seq_symbol[i];
  221.  
  222.     if (!compiling_predef) init_predef();
  223.     /* When the separate compilation facility is being used all references to
  224.      * AIS files will be made via the directory in LIBFILE. AISFILENAME is set
  225.      * to a number if the library is used, otherwise it is the FILENAME.  
  226.      */
  227.     if (lib_option) {
  228.         if (compiling_predef)
  229.             AISFILENAME = "0";
  230.         else if (new_library) 
  231.             AISFILENAME = "1";
  232.         else {
  233.             /* here to get AIS name from lib. Note the library is left open*/
  234.             AISFILENAME = lib_aisname();
  235.             read_lib();
  236.         }
  237.     }
  238.     else {
  239.         AISFILENAME = FILENAME;
  240.     }
  241.     /* open the appropriate files using the suffix  .aic for ais files and
  242.      * .trc for tree file. 
  243.      */
  244.     AISFILE  = ifopen(AISFILENAME, "aic", "w", 0);
  245.     TREFILE  = ifopen(AISFILENAME, "trc", "w", 0);
  246.     /* delete any existing stubfile for current AISFILENAME */
  247.     ifdelete(strjoin(AISFILENAME, ".st1"));
  248.     lrparse();
  249.  
  250.     unlink("COMPILE.CK$");  /*  Checked by GWAda */
  251.  
  252.     if (debugopt && errors)
  253.         printf("%d parse error(s) found.\n", errors);
  254.     fclose(adafile);
  255.     if (trcopt)
  256.         fclose(errfile);
  257.  
  258. /*
  259.     avl_w -> delete(avl_w -> avl_win1);
  260. */
  261.  
  262.     exitf(errors ? RC_ERRORS : RC_SUCCESS);
  263. }
  264.  
  265. /* 
  266.  *            Lrparse: Parser driver. 
  267.  * Gettok() is called to return the next token.
  268.  *  Action is called to compute the next action to be taken given the
  269.  *  state and current token. If the action is a reduction, the reduction
  270.  *  of the state stack is performed, the reduction of the parse stack
  271.  *  is deferred until the next shift by putting onto the queue marked by
  272.  *  topred and lastred, and the new state is computed with another call to
  273.  *  action acting as a GOTO. If the action is a shift, all deferred reductions
  274.  *  are performed, the current token is added to the parse stack, and
  275.  *  the new state is equal to the value returned by action(). When the action
  276.  *  is shift and is equal to NUM_STATES, this is an accept action, and we 
  277.  *  return. 
  278.  */
  279.  
  280. /* 
  281.  *    A stack of tokens is kept so as to conform with the addition of an 
  282.  *  error recovery routine. Tokens is the variable which is used as an
  283.  *  array to store the tokens. Tokind is the index into this array indicating
  284.  *  the next token to be returned, or -1 if there are no stored tokens.
  285.  *  The macro NEXTTOK is designed for use with this scheme. Toksiz represents
  286.  *  the size of the array being used for the token stack at any given time.
  287.  *  If we need more space, we call realloc() to give us more storage, and
  288.  *  change toksiz to reflect this change. 
  289.  */
  290.  
  291. /*
  292.   *    Changes made for error recovery        (12/28/83-NG)
  293.   *
  294.   *  Before the call to prserr(), some manipulation of the state and
  295.   *  parse stacks must be performed. A "common point" between these
  296.   *  two stacks must be kept. Before the call to prserr(), the state
  297.   *  stack from the common point must be freed, and then increased to a 
  298.   *  size equal that of the parse stack. This is done by computing
  299.   *  states from the current top of the state stack and the corresponding
  300.   *  position in the parse stack, putting the new state on top and then
  301.   *  using it to compute the next state in the same manner.
  302.   *  This common point is implemented as follows :
  303.   *  The variable sta_com_pt is a pointer to the element of the state
  304.   *  stack which corresponds to the common point. The variable 
  305.   *  prs_com_pt_ct is an integer telling how many elements, from the top
  306.   *  of the parse stack, are needed to reach that element of the parse
  307.   *  stack corresponding to the element in the state stack pointed to
  308.   *  by sta_com_pt (in terms of the sizes of the stacks below these
  309.   *  elements). After performing a shift, sta_com_pt is NULL, and 
  310.   *  prs_com_pt_ct is 0. This is because all deferred reductions will
  311.   *  have been performed, putting the two stacks in alignment. The NULL
  312.   *  indicates that the common point is above (the top of) the state
  313.   *  stack. When there is a reduction, the sta_com_pt may shift down in
  314.   *  the stack or remain the same. If it shifts downwards, then
  315.   *  prs_com_pt_ct is shifted also by the number of elements sta_com_pt
  316.   *  was shifted. (When this first happens sta_com_pt becomes non-NULL)
  317.   *     Just before the call to prserr(), first free the elements of the 
  318.   *  state stack using the pointer we have to the last element we wish
  319.   *  freed. Then copy prs_com_pt_ct elements from the top of the parse
  320.   *  stack into an array. We then compute the states from the state on top
  321.   *  of the state stack and the next element of the parse stack (from the 
  322.   *  array).
  323.   *
  324.   */
  325.  
  326.  
  327.  
  328. static void lrparse()                /*;lrparse*/
  329. {
  330.     struct two_pool *topred = NULL,    /* Top of reduction queue */
  331.     *lastred = NULL;    /* Bottom of reduction queue */
  332.     int act;                /* Pending action */
  333.     struct two_pool *tmp, *top;        /* Temps */
  334.     int n,        /* Number of symbols being reduced */
  335.     red;        /* Reduction to be performed */
  336.     struct two_pool *sta_com_pt = NULL; /* Common point stuff */
  337.     int i;
  338.     int prs_com_pt_ct = 0;
  339.     int prs_ct_flag;
  340.  
  341.     sta_stack = TALLOC();
  342.     sta_stack->val.state = 1;
  343.     sta_stack->link = NULL;
  344.     curtok = NEXTTOK;
  345.  
  346.     while (1)            /* Main parse loop */
  347.     {
  348.         /*    Determine action */
  349.  
  350. #ifdef DEBUG1
  351.         if (trcopt) {
  352.             fprintf(errfile, "action(%d, %d) = ", sta_stack->val.state, curtok->symbol);
  353.         }
  354. #endif
  355.         act = action(sta_stack->val.state, curtok->symbol);
  356. #ifdef DEBUG1
  357.         if (trcopt)
  358.             fprintf(errfile, "%d \n", act) ;
  359. #endif
  360.  
  361.         if (!act)        /* ERROR */
  362.         {
  363.             if (topred != NULL)
  364.                 errorinit(&sta_stack, &sta_com_pt, &prs_com_pt_ct) ;
  365.  
  366.             prserr(curtok);        /* THIS IS IT : PRSERR */
  367.  
  368.             curtok = NEXTTOK ;
  369.  
  370. #ifdef DEBUG
  371.             /* print debugging information */
  372.             if (trcopt) {
  373.                 fprintf(errfile, "RECOVERED\n");
  374.                 fprintf(errfile, "STATE STACK:\n");
  375.                 dump_stack(sta_stack);
  376.                 fprintf(errfile, "PARSE STACK:\n");
  377.                 dump_prsstack(prs_stack);
  378.                 fprintf(errfile, "NEXT TOKEN: %s\n", TOKSTR(curtok->symbol));
  379.             }
  380. #endif
  381.  
  382.             /* 
  383.              * Free any pending reductions 
  384.              */
  385.             if (topred != NULL) {
  386.                 TFREE(topred, lastred) ;
  387.                 topred = lastred = NULL ;
  388.             }
  389.         }
  390.  
  391.         else if (act <= NUM_STATES) /* Shift */
  392.         {
  393.             /* Perform deferred reductions on prs_stack */
  394.  
  395.             if (topred != NULL) {
  396.  
  397.                 tmp = topred;
  398.                 while (topred != NULL) {
  399.                     reduce((int)topred->val.reduction);
  400.                     topred = topred->link;
  401.                 }
  402.                 TFREE(tmp, lastred);
  403.                 lastred = NULL;
  404.             }
  405.             tmp = TALLOC();
  406.             tmp->val.state = act;
  407.             tmp->link = sta_stack;
  408.             sta_stack = tmp ;
  409.             n_sta_stack ++ ;
  410.             curtok->prev = prs_stack;
  411.             prs_stack = curtok;
  412.             PREVTOK = copytoken(curtok) ;
  413.             curtok = NEXTTOK;
  414.             n_prs ++ ; /* Increment the size of the parse stack */
  415.  
  416.             sta_com_pt = NULL;        /* Initialize comm pt stuff */
  417.             prs_com_pt_ct = 0;
  418.  
  419.             if (act == NUM_STATES)    /* Accept */
  420.                 return;
  421.         }
  422.         else /* Reduce */
  423.         {
  424.             red = act - NUM_STATES - 1;
  425.             n = rhslen[red];
  426.             tmp = TALLOC();
  427.             tmp->val.reduction = red;
  428.             tmp->link = NULL;
  429.             prs_ct_flag = 0;
  430.             if (lastred == NULL)
  431.                 topred = lastred = tmp;
  432.             else {
  433.                 lastred->link = tmp;
  434.                 lastred = tmp;
  435.             }
  436.             if (!n) {
  437.                 tmp = TALLOC();
  438.                 tmp->link = sta_stack;
  439.                 sta_stack = tmp;
  440.             }
  441.             else if (n > 1) {
  442.                 top = sta_stack;
  443.                 n_sta_stack = n_sta_stack - n + 1 ;
  444.                 for (i = n - 2; i--; ) {
  445.                     if (sta_com_pt == sta_stack)   /* The common point */
  446.                     {                   /* might be freed here */
  447.                         sta_com_pt = NULL;
  448.                         prs_ct_flag = 1;
  449.                         prs_com_pt_ct += 2;
  450.                     }
  451.                     else if (prs_ct_flag)    /* Keep count of no. of places */
  452.                         prs_com_pt_ct++;    /* common point will move */
  453.                     sta_stack = sta_stack->link;
  454.                 }
  455.                 if (sta_com_pt == sta_stack) {
  456.                     sta_com_pt = NULL;
  457.                     prs_com_pt_ct ++ ;
  458.                 }
  459.                 tmp = sta_stack;
  460.                 sta_stack = sta_stack->link;
  461.                 TFREE(top, tmp);
  462.             }
  463.  
  464.             /* Set sta_com_pt if needed, and set prs_com_pt_ct to
  465.            point to right part of prs_stack in the case in which 
  466.            this is the first reduction after a shift. */
  467.             if (sta_com_pt == NULL) {
  468.                 sta_com_pt = sta_stack;
  469.                 if (!prs_com_pt_ct)
  470.                     prs_com_pt_ct = n ;
  471.             }
  472.  
  473.             sta_stack->val.state = 
  474.                 action((int)sta_stack->link->val.state, lhs[red]);
  475.         }
  476.     }
  477. }
  478.  
  479. static void errorinit(struct two_pool **psta_stack,
  480.   struct two_pool **psta_com_pt, int *pprs_com_pt_ct)    /*;errorinit*/
  481. {
  482.     struct two_pool *tmp;
  483.     struct prsstack **tmp_prs_array;
  484.     struct prsstack *prs_temp;
  485.     int i;
  486.  
  487.     if (*psta_com_pt == NULL)
  488.         return;
  489.     tmp = (*psta_com_pt)->link;
  490.     TFREE(*psta_stack, *psta_com_pt);
  491.     *psta_stack = tmp;
  492.     *psta_com_pt = NULL;
  493.     if (!*pprs_com_pt_ct)
  494.         return;
  495.     tmp_prs_array = (struct prsstack **)malloc((unsigned)(*pprs_com_pt_ct * 
  496.       (sizeof(struct prsstack *))));
  497.     for (i = 0, prs_temp = prs_stack; i < *pprs_com_pt_ct; i++,
  498.       prs_temp = prs_temp->prev)
  499.         tmp_prs_array[i] = prs_temp;
  500.     for (i = *pprs_com_pt_ct - 1; i >= 0; i--) {
  501.         tmp = TALLOC();
  502.         tmp->link = *psta_stack;
  503.         tmp->val.state = action((int)(*psta_stack)->val.state,
  504.           tmp_prs_array[i]->symbol);
  505.         *psta_stack = tmp;
  506.     }
  507.     free((char *)tmp_prs_array);
  508.     *pprs_com_pt_ct = 0;
  509. }
  510.  
  511. struct prsstack *tokfromlist()            /*;tokfromlist*/
  512. {
  513.     int tmp = tokind;
  514.  
  515.     tokind = (tokind - 1 + toksiz) % toksiz;
  516.     return(tokens[tmp]);
  517. }
  518.  
  519. static void exitf(int status)                                        /*;exitf*/
  520. {
  521.     /* exit after closing any unclosed files */
  522.  
  523.     ifoclose(AISFILE);
  524.     ifoclose(STUBFILE);
  525.     ifoclose(TREFILE);
  526.     exitp(status);
  527. }
  528.  
  529.